package org.NooLab.randomgraph.components;

import java.util.ArrayList;

import org.NooLab.structures.randomgraph.FingerPrintMatrixIntf;
import org.NooLab.utilities.strings.ArrUtilities;



/**
 * 
 * 
 * 
 *
 */
public class FingerPrintMatrix implements FingerPrintMatrixIntf{

	// scheme is rows( of columns), the outer list are the rows
	ArrayList<ArrayList<Double>> fmatrix = new ArrayList<ArrayList<Double>>() ;
	ArrayList<Double> concatenatedFMatrix = null ;
	
	int rowCount=0;
	
	public FingerPrintMatrix( int rowcount){
		rowCount = rowcount;
		
		init();
	}
	
	private void init(){
		
		ArrayList<Double> row;
		
		for (int i=0;i<rowCount;i++){
			row = new ArrayList<Double>();
			fmatrix.add(row) ;
		}
		
	}
	
	public void close() {
		// 
		
		for (int i=0;i<fmatrix.size();i++){
			fmatrix.get(i).clear(); 
		}
		if (fmatrix!=null){
			fmatrix.clear();
		}
		if (concatenatedFMatrix!=null){
			concatenatedFMatrix.clear() ;
		}
	}

	public void clear() {
		// all components==rows first separately
		fmatrix.clear();
	}

	public void addAll(FingerPrintMatrixIntf fingerPrintMatrix) {
		int k=0,n;
		ArrayList<Double> mrow = new ArrayList<Double>();
		
		if (fmatrix == fingerPrintMatrix.getFmatrix()){
			return;
		}
		n = fingerPrintMatrix.getFmatrix().size();
		
		for (int r=0; r<n;r++){
		 
			
			fmatrix.add( new ArrayList<Double>() ) ;
			fmatrix.get(r).addAll(  fingerPrintMatrix.getFmatrix().get(r)) ;
			 
		}
		k=k+1-1;
	}

	/**
	 * this is summing the new profile to the row selected by the index 
	 * 
	 * @param rowIndex
	 * @param fprofile
	 */
	public boolean addProfileToRow( int rowIndex, ArrayList<Double> fprofile){
	
		boolean rB=true;
		ArrayList<Double> values;
		
		if (rowIndex<fmatrix.size()){
			if (fmatrix.get(rowIndex).size()==0){
				fmatrix.get(rowIndex).addAll(fprofile) ;
			}else{
				values = fmatrix.get(rowIndex);
				values = (new ArraySum(values, fprofile,1)).calc();
			}
		}else{
			rB=false;
		}
		
		return rB;
	}

	public void calcAverages(int n, ArrayList<Integer> missingValCounters) {
		//
		double v;
		int cn;
		
		for (int r=0;r<fmatrix.size();r++){
			cn=n;
			cn = Math.max(1,cn - missingValCounters.get(r));
			
			for (int c=0;c<fmatrix.get(r).size();c++){
				v = fmatrix.get(r).get(c) ;
				v = v/((double) cn);
				fmatrix.get(r).set(c,v) ;
			} // c->
		}// r->
 
	}

	public void concatenate( int coreWordPos ) {
		
		boolean hb;
		concatenatedFMatrix = new ArrayList<Double>(); 
		
		if (coreWordPos>=0){
			concatenatedFMatrix.addAll( fmatrix.get(coreWordPos)) ;
		}
		
		for (int r=0;r<fmatrix.size();r++){
			hb = true;
			if (coreWordPos>=0){
				if (r!=coreWordPos){
					hb=true;
				}
			}
			if (hb){
				concatenatedFMatrix.addAll( fmatrix.get(r)) ;
			}
			
		}// r->
		
	}

	public ArrayList<ArrayList<Double>> getFmatrix() {
		return fmatrix;
	}

	public void setFmatrix(ArrayList<ArrayList<Double>> fmatrix) {
		this.fmatrix = fmatrix;
	}

	public ArrayList<Double> getConcatenatedFMatrix() {
		return concatenatedFMatrix;
	}

	public void setConcatenatedFMatrix(ArrayList<Double> concatenatedFMatrix) {
		this.concatenatedFMatrix = concatenatedFMatrix;
	}

	public int getRowCount() {
		return rowCount;
	}

	public void setRowCount(int rowCount) {
		this.rowCount = rowCount;
	}
	
	
}
// ----------------------------------------------------------------------------

class ArraySum{
	
	ArrayList<Double> values1;
	ArrayList<Double> values2;
	int lenMode;
	
	// ................................................
	public ArraySum(ArrayList<Double> values1, ArrayList<Double> values2, int lenMode){
		this.values1 = values1;
		this.values2 = values2;
		this.lenMode = lenMode;
	}
	// ................................................
	public ArrayList<Double> calc() {
	
		// make it dependent on usemode, 1=use values1, 2=use values2, 0=create a new liat
		ArrayList<Double> rvalues = values1; 
		double v;
		int n=values1.size() ;
		
		for (int i=0;i<n;i++){
			if ((values1.size()<=i) || (values2.size()<=i)){
				continue;
			}
			v = values1.get(i) + values2.get(i) ;
			rvalues.set(i, v);
		}
		
		return rvalues;
	}
}

	
	
